/**
 * @file laydate - 测试
 * @author xuexb <fe.xiaowu@gmail.com>
 */

/* global layui */
/* eslint-disable max-nested-callbacks, fecs-indent */

var $ = layui.$;
var laydate = layui.laydate;
var lay = window.lay;

/**
 * 是否基于`phantomjs`测试, 因为有些特殊的case在ie中是不可用的, 比如: `window.event = {}`
 *
 * @const
 * @type {boolean}
 */
var IS_PHANTOMJS = layui.device('phantomjs').phantomjs;

/**
 * 创建dom元素, 并返回 jquery 对象
 *
 * @inner
 *
 * @param  {string} html 标签
 *
 * @return {jQuery}
 */
var createNode = function (html) {
    return $(html).addClass('test-node').appendTo('body');
};


/**
 * 日期格式化
 *
 * @inner
 *
 * @param {string} str 格式
 * @param {Date|number|string} date 时间对象或者时间缀
 * @return {string}
 *
 * @example
 * yyyy-MM-dd hh:mm:ss.S
 * yyyy-MM-dd E HH:mm:ss
 * yyyy-MM-dd EE hh:mm:ss
 * yyyy-MM-dd EEE hh:mm:ss
 * yyyy-M-d h:m:s.S
 */
var dateFormat = function (str, date) {
    str = str || 'yyyy-MM-dd HH:mm';

    if (date) {
        if ('number' === typeof date && String(date).length !== 13) {
            var temp = new Date();
            temp.setDate(temp.getDate() + date);
            date = temp;
        } else if (!(date instanceof Date)) {
            date = new Date(date);
        }
    } else {
        date = new Date();
    }

    var getTime = {
        'M+': date.getMonth() + 1,
        'd+': date.getDate(),
        'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12,
        'H+': date.getHours(),
        'm+': date.getMinutes(),
        's+': date.getSeconds(),
        'S': date.getMilliseconds()
    };

    // 如果有年
    if (/(y+)/i.test(str)) {
        // RegExp.$1为上次正则匹配的第1个结果，那么length就不用说了吧
        str = str.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
    }

    layui.each(getTime, function (key) {
        if (new RegExp('(' + key + ')').test(str)) {
            str = str.replace(RegExp.$1, (RegExp.$1.length === 1)
                ? (getTime[key])
                : (('00' + getTime[key]).substr(('' + getTime[key]).length)));
        }
    });

    return str;
};

describe('laydate', function () {
    // 输出测试节点
    beforeEach(function () {
        createNode('<div id="test-div"></div>');
        createNode('<input id="test-input" type="text">');
    });

    // 删除节点
    afterEach(function () {
        $('.layui-laydate, .test-node').remove();
    });

    it('version', function () {
        expect(laydate.v).to.be.a('string');
        expect(laydate.v).to.not.be.empty;
    });

    it('loaded css link', function () {
        // 验证页面元素
        expect($('#layuicss-laydate').length).to.equal(1, '加载laydate.css的link标签必须存在');
        expect($('#layuicss-laydate').css('display')).to.equal('none', '验证laydate.css是否生效');

        // 验证一个不存在的元素
        expect($('#layuicss-laydate-no-suceess').css('display')).to.be.undefined;
    });

    describe('laydate.render()', function () {
        it('check params and return value', function () {
            expect(laydate.render()).to.be.a('object', 'render() 返回值必须是对象');
            expect(laydate.render('str')).to.have.property('hint');
            expect(laydate.render().hint).to.be.a('function', 'render() 返回值必须包含 hint()');
            expect(laydate.render({})).to.have.property('config');
        });

        describe('options.elem', function () {
            it('selector', function () {
                expect(function () {
                    laydate.render({
                        elem: '#test-div'
                    });

                    laydate.render({
                        elem: '#test-div-layui'
                    });

                    laydate.render({
                        elem: '.ok-layui'
                    });
                }).to.not.throw;

                expect($('.layui-laydate').length).to.equal(0);
            });

            it('error selector', function () {
                expect(function () {
                    laydate.render({
                        elem: '#test-div-no-selector',
                        show: true
                    });

                    laydate.render({
                        elem: '.test-div-no-selector',
                        show: true
                    });

                }).to.not.throw;

                expect($('.layui-laydate').length).to.equal(0);
            });
        });

        describe('options.type', function () {
            it('default value', function () {
                expect(laydate.render().config.type).to.equal('date');
                expect(laydate.render({
                    elem: '#test-div'
                }).config.type).to.equal('date', 'render 方法 options.type 默认值必须是 date');
            });

            // 先不作错误值的校验了
            // it('error value', function () {
            //   expect(function () {
            //     laydate.render({
            //       elem: '#test-div',
            //       type: 'layui'
            //     });
            //   }).to.throw();
            // });

            it('is year', function (done) {
                var result = laydate.render({
                    elem: '#test-div',
                    type: 'year',
                    show: true
                });

                expect(result.config.type).to.equal('year');

                setTimeout(function () {
                    expect($('.laydate-set-ym').length).to.equal(1, '标头年月元素必须存在');
                    expect($('.laydate-year-list .layui-this').text()).to.equal(dateFormat('yyyy年'), '默认高亮显示当前年');

                    $('.laydate-btns-confirm').click();
                    expect($('#test-div').text()).to.equal(dateFormat('yyyy'), '确认后输出选中的值');
                    done();
                }, 100);
            });

            it('is month', function (done) {
                var result = laydate.render({
                    elem: '#test-div',
                    type: 'month',
                    show: true
                });

                expect(result.config.type).to.equal('month');

                setTimeout(function () {
                    expect($('.laydate-set-ym').length).to.equal(1);
                    expect($('.laydate-month-list .layui-this').attr('lay-ym'))
                        .to.equal(dateFormat('M') - 1 + '', '默认高亮显示当前月');

                    $('.laydate-btns-confirm').click();
                    expect($('#test-div').text()).to.equal(dateFormat('yyyy-MM'), '确认后输出选中的值');
                    done();
                });
            });

            it('is date', function (done) {
                var result = laydate.render({
                    elem: '#test-div',
                    type: 'date',
                    show: true
                });

                expect(result.config.type).to.equal('date');

                setTimeout(function () {
                    expect($('.laydate-set-ym').text()).to.equal(dateFormat('yyyy年M月'), '标头内显示当前年+月');
                    expect($('.layui-laydate-content .layui-this').attr('lay-ymd'))
                        .to.equal(dateFormat('yyyy-M-d'), '默认高亮显示当前日');

                    $('.laydate-btns-confirm').click();
                    expect($('#test-div').text()).to.equal(dateFormat('yyyy-MM-dd'), '确认后输出选中的值');
                    done();
                });
            });

            it('is time', function (done) {
                var result = laydate.render({
                    elem: '#test-div',
                    type: 'time',
                    show: true
                });

                expect(result.config.type).to.equal('time');

                setTimeout(function () {
                    expect($('.laydate-time-text').text()).to.equal('选择时间', '标头内显示当前年+月');
                    expect($('.laydate-time-list').length).to.equal(1);

                    expect($('#test-div').text()).to.equal('');
                    $('.laydate-btns-confirm').click();
                    expect($('#test-div').text()).to.equal('00:00:00');
                    done();
                });
            });

            it('is datetime', function (done) {
                var result = laydate.render({
                    elem: '#test-div',
                    type: 'datetime',
                    show: true
                });
                var now = new Date();

                expect(result.config.type).to.equal('datetime');

                setTimeout(function () {
                    expect($('.laydate-set-ym').text()).to.equal(
                        now.getFullYear() + '年' + (now.getMonth() + 1) + '月',
                        '标头内显示当前年+月'
                    );
                    expect($('.layui-laydate-content .layui-this').attr('lay-ymd')).to.equal(
                        now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate(),
                        '默认高亮显示当前日'
                    );
                    expect($('.laydate-btns-time').text()).to.equal('选择时间');
                    expect($('.laydate-time-text').text()).to.equal('');

                    // 断定选择时间的切换
                    $('.laydate-btns-time').click();
                    expect($('.laydate-time-text').text()).to.equal('选择时间');
                    expect($('.laydate-btns-time').text()).to.equal('返回日期');
                    $('.laydate-btns-time').click();
                    expect($('.laydate-time-text').text()).to.equal('');
                    expect($('.laydate-btns-time').text()).to.equal('选择时间');

                    $('.laydate-btns-confirm').click();
                    expect($('#test-div').text()).to.equal(dateFormat('yyyy-MM-dd 00:00:00'), '确认后输出选中的值');
                    done();
                });
            });
        });

        describe('options.range', function () {
            it('time type and range', function (done) {
                laydate.render({
                    elem: '#test-div',
                    type: 'time',
                    range: true,
                    show: true
                });

                setTimeout(function () {
                    expect($('.laydate-time-text').length).to.equal(2);
                    $('.laydate-btns-confirm').click();
                    expect($('#test-div').text()).to.equal('00:00:00 - 00:00:00', '确认后输出范围值');
                    done();
                });
            });

            it('year type and range is split', function () {
                laydate.render({
                    elem: '#test-div',
                    type: 'year',
                    range: '到',
                    show: true
                });

                $('.laydate-btns-confirm').click();
                expect($('#test-div').text()).to.match(/\d+\s到\s\d+/, '确认后输出范围值');
            });
        });

        describe('options.format', function () {
            it('default value', function () {
                expect(laydate.render().config.format).to.equal('yyyy-MM-dd');
                expect(laydate.render({
                    elem: '#test-div'
                }).config.format).to.equal('yyyy-MM-dd', 'render 方法 options.format 默认值必须是 yyyy-MM-dd');
            });

            it('yyyy年MM月dd日 HH时mm分ss秒', function () {
                var result = laydate.render({
                    format: 'yyyy年MM月dd日 HH时mm分ss秒',
                    elem: '#test-div'
                });

                expect(result.config.format).to.equal('yyyy年MM月dd日 HH时mm分ss秒', '设置 option.format 返回配置内必须相等');
                $('#test-div').click();
                $('.laydate-btns-confirm').click();
                expect($('#test-div').text()).to.equal(dateFormat('yyyy年MM月dd日 00时00分00秒'), '确认后输出选中的值');
            });

            it('datetime type and yyyy年的M月某天晚上，大概H点', function () {
                laydate.render({
                    format: 'yyyy年的M月某天晚上，大概H点',
                    elem: '#test-div',
                    type: 'datetime'
                });

                $('#test-div').click();
                $('.laydate-btns-time').click();
                $('.laydate-time-list li').eq(0).find('li').eq(5).click();
                $('.laydate-btns-confirm').click();
                expect($('#test-div').text()).to.equal(dateFormat('yyyy年的M月某天晚上，大概5点'), '确认后输出选中的值');
            });

            it('format and error value', function () {
                laydate.render({
                    elem: '#test-div',
                    value: '2017年7月7日',
                    format: 'yyyy~MM~dd'
                });

                expect($('#test-div').text()).to.equal('2017年7月7日', '默认输出value的值到元素中');
                $('#test-div').click();
                expect($('#test-div').text()).to.equal(dateFormat('yyyy~MM~dd'), '根据options.format修正value为当天');

                // 错误提示
                expect($('.layui-laydate-hint').text()).to.match(/日期格式不合法/);
                expect($('.layui-laydate-hint').text()).to.match(/yyyy~MM~dd/);
            });

            // 验证当format为 yyyyMMdd 和 value=20170707 时是否通过
            it('format and number value', function (done) {
                laydate.render({
                    elem: '#test-div',
                    value: '20170707',
                    format: 'yyyyMMdd',
                    show: true
                });

                laydate.render({
                    elem: '#test-input',
                    value: '201777',
                    format: 'yyyyMd',
                    show: true
                });

                expect($('#test-div').text()).to.equal('20170707', '默认输出value的值到元素中');
                expect($('#test-input').val()).to.equal('201777', '默认输出value的值到元素中');

                setTimeout(function () {
                    // 错误提示
                    expect($('.layui-laydate-hint').length).to.equal(0, '格式正确没有错误提示');

                    done();
                });
            });
        });

        describe('options.value', function () {
            it('2017-06-31', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-06-31',
                    done: function (value) {
                        expect(value).to.equal('2017-06-30', '6月最大为30号');
                        done();
                    }
                });

                $('.laydate-btns-confirm').click();
            });

            it('new Date()', function (done) {
                var date = new Date();
                date.setDate(date.getDate() + 1);

                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: date,
                    done: function (value) {
                        expect(value).to.equal(dateFormat('yyyy-MM-dd', 1));
                        done();
                    }
                });

                $('.laydate-btns-confirm').click();
            });

            it('yyyy-MM-dd', function () {
                laydate.render({
                    elem: '#test-div',
                    value: '1990年11月27日',
                    format: 'yyyy年MM月dd日'
                });

                $('#test-div').click();
                $('.laydate-btns-confirm').click();
                expect($('#test-div').text()).to.equal('1990年11月27日', '确认后输出选中的值');
            });

            it('yyyy-MM-dd not format value', function () {
                laydate.render({
                    elem: '#test-div',
                    value: '1990-11月-日',
                    format: 'yyyy年MM月dd日'
                });

                $('#test-div').click();

                // 错误提示
                expect($('.layui-laydate-hint').text()).to.match(/日期格式不合法/);
                expect($('.layui-laydate-hint').text()).to.match(/yyyy年MM月dd日/);

                $('.laydate-btns-confirm').click();
                expect($('#test-div').text()).to.equal(dateFormat('yyyy年MM月dd日'), '确认后输出选中的值');
            });

            it('number not format value', function () {
                laydate.render({
                    elem: '#test-div',
                    value: Date.now()
                });

                $('#test-div').click();

                // 错误提示
                expect($('.layui-laydate-hint').text()).to.match(/日期格式不合法/);
            });

            it('div default html value format error', function () {
                laydate.render({
                    elem: '#test-div',
                    value: Date.now()
                });

                $('#test-div').text('layui').click();

                // 错误提示
                expect($('.layui-laydate-hint').text()).to.match(/日期格式不合法/);
            });

            it('input default value format error', function (done) {
                createNode('<input id="test-input-2" type="text" value="layui">');

                laydate.render({
                    elem: '#test-input-2',
                    show: true
                });

                // 错误提示
                setTimeout(function () {
                    expect($('.layui-laydate-hint').text()).to.match(/日期格式不合法/);
                    done();
                });
            });

            // 当元素值更新后, 再次显示日历时会更新
            it('change value', function () {
                laydate.render({
                    show: true,
                    value: '2017-3-7',
                    elem: '#test-div'
                });

                expect($('.layui-this').text()).to.equal('7', '显示默认的7');

                $('.laydate-btns-confirm').click();
                $('#test-div').text('2017-7-10').click();
                expect($('.layui-this').text()).to.equal('10', '显示更新后的10');
            });
        });

        describe('options.min and options.max', function () {
            it('date string', function () {
                laydate.render({
                    elem: '#test-div',
                    min: '2017-7-7',
                    max: '2017-7-8',
                    value: '2017-7-8'
                });

                $('#test-div').click();
                $('.laydate-set-ym').find('[lay-type="year"]').click();
                expect($('.laydate-year-list .layui-this').text()).to.equal('2017年');

                // 只有2017年可用
                expect($('.laydate-year-list [lay-ym="2016"]').hasClass('laydate-disabled')).to.be.true;
                expect($('.laydate-year-list [lay-ym="2018"]').hasClass('laydate-disabled')).to.be.true;

                $('#test-div').click();
                $('.laydate-set-ym').find('[lay-type="month"]').click();

                // 只有7月可用
                expect($('.laydate-month-list [lay-ym="5"]').hasClass('laydate-disabled')).to.be.true;
                expect($('.laydate-month-list [lay-ym="7"]').hasClass('laydate-disabled')).to.be.true;
            });

            // 错误字符串时直接设为当天最小
            it('error string', function () {
                laydate.render({
                    elem: '#test-div',
                    min: 'layui',
                    max: 'layui'
                });

                $('#test-div').click();

                expect($('.layui-laydate-content .layui-this').attr('lay-ymd')).to.equal(dateFormat('yyyy-M-d'), '默认选中日期');

                // 昨天不可用, 判断是为了处理跨月
                var $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', -1) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.true;
                }

                // 明天不可用, 判断是为了处理跨月
                $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', 1) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.true;
                }
            });

            it('date number', function () {
                laydate.render({
                    elem: '#test-div',
                    min: -2,
                    max: 2
                });

                $('#test-div').click();

                // 前两天应该是可用, 判断是为了处理跨月
                var $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', -2) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.false;
                }

                // 前三天应该是禁用的
                $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', -3) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.true;
                }

                // 后两天可用
                $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', 2) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.false;
                }

                // 后三天禁用
                $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', 3) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.true;
                }
            });

            it('timestamp', function () {
                var date = new Date();
                var date2 = new Date();

                // 获取前三天的时间缀
                date.setDate(date.getDate() + -3);
                date2.setDate(date2.getDate() + 3);

                laydate.render({
                    elem: '#test-div',
                    min: date.getTime(),
                    max: date2.getTime()
                });

                $('#test-div').click();

                // 前三天可用, 防止跨月
                var $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', -3) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.false;
                }

                // 前四天不可用
                $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', -4) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.true;
                }

                // 后三天可用
                $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', 3) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.false;
                }

                // 后四天不可用
                $elem = $('.layui-laydate-content [lay-ymd="' + dateFormat('yyyy-M-d', 4) + '"]');
                if ($elem.length) {
                    expect($elem.hasClass('laydate-disabled')).to.be.true;
                }
            });

            it('and options.value', function () {
                laydate.render({
                    elem: '#test-div',
                    min: '2017-7-7',
                    max: '2017-7-7',
                    value: '2017-7-7'
                });

                $('#test-div').click();

                expect($('.layui-laydate-content .layui-this').attr('lay-ymd')).to.equal('2017-7-7', '默认选中日期');
                expect($('.layui-laydate-content [lay-ymd="2017-7-6"]').hasClass('laydate-disabled')).to.be.true;
                expect($('.layui-laydate-content [lay-ymd="2017-7-8"]').hasClass('laydate-disabled')).to.be.true;
            });

            // 当最大小于最小时, 日期选择都不可用
            it('options.max < options.min', function () {
                laydate.render({
                    elem: '#test-div',
                    min: '2017-7-7',
                    max: '2017-7-1'
                });

                $('#test-div').click();
                $('.laydate-set-ym').find('[lay-type="year"]').click();

                // 查找可用的年
                var year = $('.laydate-year-list li').filter(function () {
                    return !$(this).hasClass('laydate-disabled');
                }).get();
                expect(year.length).to.equal(0);

                $('#test-div').click();
                $('.laydate-set-ym').find('[lay-type="month"]').click();

                // 查找可用的月
                var month = $('.laydate-month-list li').filter(function () {
                    return !$(this).hasClass('laydate-disabled');
                }).get();
                expect(month.length).to.equal(0);
            });
        });

        describe('options.trigger', function () {
            it('default value', function () {
                var result = laydate.render({
                    elem: '#test-input'
                });
                expect(result.config.trigger).to.equal('focus');

                result = laydate.render({
                    elem: '#test-div'
                });
                // div会默认转成click
                expect(result.config.trigger).to.equal('click');
            });

            it('not click', function (done) {
                laydate.render({
                    elem: '#test-div',
                    trigger: 'layui',
                    ready: done
                });

                $('#test-div').click();

                setTimeout(done);
            });
        });

        describe('options.show', function () {
            it('default value', function (done) {
                laydate.render({
                    elem: '#test-div',
                    ready: done
                });
                setTimeout(done);
            });

            it('show is true', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    ready: function () {
                        done();
                    }
                });
            });

            // 以下2个是测试和`options.closeStop`的配合
            it('element trigger show', function (done) {
                createNode('<button id="test-trigger-show">显示</button>');
                $('#test-trigger-show').on('click', function () {
                    laydate.render({
                        elem: '#test-div',
                        show: true
                    });
                }).click();

                setTimeout(function () {
                    expect($('.layui-laydate').length).to.equal(0);
                    done();
                }, 100);
            });
            it('element trigger show and options.closeStop', function (done) {
                createNode('<button id="test-trigger-show">显示</button>');
                $('#test-trigger-show').on('click', function () {
                    laydate.render({
                        elem: '#test-div',
                        show: true,
                        closeStop: '#test-trigger-show'
                    });
                }).click();

                setTimeout(function () {
                    expect($('.layui-laydate').length).to.equal(1);
                    done();
                }, 100);
            });
        });

        describe('options.position', function () {
            it('static', function () {
                laydate.render({
                    elem: '#test-div',
                    position: 'static'
                });

                expect($('#test-div').find('.layui-laydate-static').length).to.equal(1);
            });

            it('fixed', function () {
                laydate.render({
                    elem: '#test-div',
                    position: 'fixed',
                    show: true
                });

                expect($('.layui-laydate').css('position')).to.equal('fixed');
            });
        });

        describe('options.zIndex', function () {
            it('options.position is fixed', function () {
                laydate.render({
                    elem: '#test-div',
                    position: 'fixed',
                    show: true,
                    zIndex: 10086
                });

                expect($('.layui-laydate').css('zIndex')).to.equal('10086');
            });

            it('options.position is abolute', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    position: 'abolute',
                    zIndex: 10086
                });

                expect($('.layui-laydate').css('zIndex')).to.equal('10086');
            });

            it('options.position is static', function () {
                laydate.render({
                    elem: '#test-div',
                    position: 'static',
                    show: true,
                    zIndex: 10086
                });

                expect($('.layui-laydate').css('zIndex')).to.equal('10086');
            });
        });

        describe('options.showBottom', function () {
            it('default value', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true
                });

                expect($('.layui-laydate-footer').length).to.equal(1);
            });

            it('is false', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    showBottom: false
                });

                expect($('.layui-laydate-footer').length).to.equal(0);
            });
        });

        describe('options.btns', function () {
            it('default value', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true
                });

                var btns = $('.laydate-footer-btns span').map(function () {
                    return $(this).attr('lay-type');
                }).get();

                expect(btns).to.deep.equal([
                    'clear',
                    'now',
                    'confirm'
                ]);
            });

            it('[confirm, now]', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    btns: ['confirm', 'now']
                });

                var btns = $('.laydate-footer-btns span').map(function () {
                    return $(this).attr('lay-type');
                }).get();

                expect(btns).to.deep.equal([
                    'confirm',
                    'now'
                ]);
            });

            it('error value', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    btns: ['layui']
                });

                var btns = $('.laydate-footer-btns span').map(function () {
                    return $(this).attr('lay-type');
                }).get();

                expect(btns).to.deep.equal([
                    'layui'
                ]);
            });
        });

        describe('options.lang', function () {
            it('default value is cn', function () {
                var result = laydate.render({
                    show: true,
                    elem: '#test-div'
                });

                var weeks = $('.layui-laydate-content').find('thead th').map(function () {
                    return $(this).text();
                }).get();
                expect(weeks).to.deep.equal(['日', '一', '二', '三', '四', '五', '六'], 'cn版本星期的标头');

                expect($('.laydate-btns-confirm').text()).to.equal('确定', 'cn版本确定按钮');
                expect($('.laydate-btns-now').text()).to.equal('现在', 'cn版本当前按钮');
                expect($('.laydate-btns-clear').text()).to.equal('清空', 'cn版本清除按钮');
                expect(result.config.lang).to.equal('cn');
            });

            it('en', function () {
                var result = laydate.render({
                    show: true,
                    lang: 'en',
                    elem: '#test-div'
                });

                var weeks = $('.layui-laydate-content').find('thead th').map(function () {
                    return $(this).text();
                }).get();
                expect(weeks).to.deep.equal(['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], 'en版本星期的标头');

                expect($('.laydate-btns-confirm').text()).to.equal('Confirm', 'en版本确定按钮');
                expect($('.laydate-btns-now').text()).to.equal('Now', 'en版本当前按钮');
                expect($('.laydate-btns-clear').text()).to.equal('Clear', 'en版本清除按钮');
                expect(result.config.lang).to.equal('en');
            });

            it('error vaue', function () {
                var result = laydate.render({
                    show: true,
                    lang: 'layui',
                    elem: '#test-div'
                });

                expect($('.laydate-btns-confirm').text()).to.equal('确定', 'lang错误时默认为中文');
                expect(result.config.lang).to.equal('layui');
            });

            // todo month, time, timeTips
        });

        describe('options.theme', function () {
            it('molv', function () {
                laydate.render({
                    show: true,
                    elem: '#test-div',
                    theme: 'molv'
                });

                expect($('.laydate-theme-molv').length).to.equal(1, '墨绿主题class存在');
            });

            it('grid', function () {
                laydate.render({
                    show: true,
                    elem: '#test-div',
                    theme: 'grid'
                });

                expect($('.laydate-theme-grid').length).to.equal(1, '格子主题class存在');
            });

            it('error value', function () {
                laydate.render({
                    show: true,
                    elem: '#test-div',
                    theme: 'layui-test'
                });

                expect($('.laydate-theme-layui-test').length).to.equal(1, '自定义主题class存在');
            });

            it('#color', function () {
                // 主要处理多浏览器兼容
                var colors = [
                    'rgb(0, 0, 0)',
                    'rgba(0, 0, 0, 0)',
                    '#000'
                ];

                laydate.render({
                    show: true,
                    elem: '#test-div',
                    theme: '#000'
                });

                $.each([
                    '.layui-this',
                    '.layui-laydate-header'
                ], function (index, selector) {
                    expect(colors).to.includes($(selector).css('background-color'), '标头和当前选中颜色必须是设置的');
                });
            });
        });

        describe('options.calendar', function () {
            it('default value', function () {
                var result = laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-3-8'
                });

                expect(result.config.calendar).to.equal(false, '默认值为false');
                expect($('.layui-this').text()).to.equal('8', '显示数字');
            });

            it('is true', function () {
                var result = laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-3-8',
                    calendar: true
                });

                expect(result.config.calendar).to.equal(true, '默认值为false');
                expect($('.layui-this').text()).to.equal('妇女', '显示妇女节');
            });

            it('options.lang is en', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    lang: 'en',
                    value: '2017-3-8'
                });

                expect($('.layui-this').text()).to.equal('8', '国际版显示数字');
            });
        });

        describe('options.mark', function () {
            it('every year', function () {
                laydate.render({
                    mark: {
                        '0-3-7': '妹子'
                    },
                    show: true,
                    value: '2017-3-7',
                    elem: '#test-div'
                });

                expect($('.layui-this').text()).to.equal('妹子', '显示自定义的妹子');

                // 再看下4月7日
                $('.laydate-btns-confirm').click();
                $('#test-div').text('2017-4-7').click();
                expect($('.layui-this').text()).to.equal('7', '显示日期');
            });

            it('every year and month', function () {
                laydate.render({
                    mark: {
                        '0-0-7': '妹子'
                    },
                    show: true,
                    value: '2017-7-7',
                    elem: '#test-div'
                });

                expect($('.layui-this').text()).to.equal('妹子', '显示自定义的妹子');

                // 再看下4月7日
                $('.laydate-btns-confirm').click();
                $('#test-div').text('2017-4-7').click();
                expect($('.layui-this').text()).to.equal('妹子', '显示自定义的妹子');
            });

            it('yyyy-M-d', function () {
                laydate.render({
                    mark: {
                        '2017-3-7': '妹子'
                    },
                    show: true,
                    value: '2017-3-7',
                    elem: '#test-div'
                });

                expect($('.layui-this').text()).to.equal('妹子', '显示自定义的妹子');

                // 再看下2016年
                $('.laydate-btns-confirm').click();
                $('#test-div').text('2016-3-7').click();
                expect($('.layui-this').text()).to.equal('7', '显示日期');
            });

            it('options.calendar is true', function () {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-3-8',
                    mark: {
                        '2017-3-8': '快乐'
                    },
                    calendar: true
                });

                expect($('.layui-this').text()).to.equal('快乐', '显示被mark覆盖的 快乐');
            });
        });

        // 基于phantomjs测试内部方法
        if (IS_PHANTOMJS) {
            it('options.dateTime', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    dateTime: {
                        year: 20000000,
                        month: 15,
                        minutes: 70,
                        seconds: 60,
                        hours: 25
                    },
                    done: function (value) {
                        expect(value).to.equal(dateFormat('yyyy-MM-dd'), '设置日期超出范围, 初始化为当天');
                        done();
                    }
                });

                $('.laydate-btns-confirm').click();
            });
        }
    });

    describe('callbacks', function () {
        describe('render', function () {
            it('not elem', function (done) {
                var flag = true;
                laydate.render({
                    ready: function () {
                        flag = false;
                    }
                });

                setTimeout(function () {
                    expect(flag).to.be.true;
                    done();
                }, 360);
            });

            it('trigger', function (done) {
                laydate.render({
                    elem: '#test-div',
                    ready: function (data) {
                        expect(data).to.be.a('object');
                        done();
                    }
                });

                $('#test-div').click();
            });

            // 如果是div则自动切换成click
            it('multiple trigger', function (done) {
                var index = 0;

                laydate.render({
                    elem: '#test-div',
                    ready: function () {
                        index += 1;
                    }
                });
                $('#test-div').click().click().click();

                setTimeout(function () {
                    expect(index).to.equal(3);
                    done();
                });
            });

            // 当show=true时应该直接显示并执行ready事件
            it('options.show is true', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    ready: function (data) {
                        expect(data).to.be.a('object');
                        done();
                    }
                });
            });
        });

        describe('change', function () {
            it('trigger', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-07-07',
                    range: false,
                    change: function (value, date, endDate) {
                        expect(value).to.equal('2017-08-07', '进入下一月的日期');
                        expect(date).to.deep.equal({
                            year: 2017,
                            month: 8,
                            date: 7,
                            hours: 0,
                            minutes: 0,
                            seconds: 0
                        }, '进入下一月的日期时间对象');
                        expect(endDate).to.deep.equal({}, '没有开启 options.range 时 endDate 为空对象');

                        done();
                    }
                });

                $('.laydate-next-m').click();
            });

            it('options.range is true', function (done) {
                laydate.render({
                    elem: '#test-div',
                    range: true,
                    show: true,
                    change: function (value, date, endDate) {
                        var start = dateFormat('yyyy-MM-dd');
                        var end = dateFormat('yyyy-MM-dd', 1);

                        // expect(value).to.equal(start + ' - ' + end, '进入下一月的日期');
                        expect(date).to.be.a('Object');
                        expect(date).to.not.deep.equal({});
                        expect(endDate).to.be.a('Object');
                        expect(endDate).to.not.deep.equal({}, '开启 options.range 时 endDate 不能为空');

                        done();
                    }
                });

                // 模拟点击当天和下一天
                $('[lay-ymd="' + dateFormat('yyyy-M-d') + '"]').click();
                $('[lay-ymd="' + dateFormat('yyyy-M-d', 1) + '"]').click();
            });
        });

        describe('done', function () {
            it('click date', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-07-07',
                    range: false,
                    done: function (value, date, endDate) {
                        expect(value).to.equal('2017-07-07');
                        expect(date).to.deep.equal({
                            year: 2017,
                            month: 7,
                            date: 7,
                            hours: 0,
                            minutes: 0,
                            seconds: 0
                        });
                        expect(endDate).to.deep.equal({});

                        done();
                    }
                });

                $('.layui-this').click();
            });

            it('click confirm btn', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-07-07',
                    range: false,
                    done: function (value, date, endDate) {
                        expect(value).to.equal('2017-07-07');
                        expect(date).to.deep.equal({
                            year: 2017,
                            month: 7,
                            date: 7,
                            hours: 0,
                            minutes: 0,
                            seconds: 0
                        });
                        expect(endDate).to.deep.equal({});

                        done();
                    }
                });

                $('.laydate-btns-confirm').click();
            });

            it('click clear btn', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-07-07',
                    range: false,
                    done: function (value, date, endDate) {
                        expect(value).to.equal('');
                        expect(date).to.deep.equal({});
                        expect(endDate).to.deep.equal({});

                        done();
                    }
                });

                $('.laydate-btns-clear').click();
            });

            it('click now btn', function (done) {
                laydate.render({
                    elem: '#test-div',
                    show: true,
                    value: '2017-07-07',
                    range: false,
                    done: function (value, date, endDate) {
                        expect(value).to.equal(dateFormat('yyyy-MM-dd'));

                        done();
                    }
                });

                $('.laydate-btns-now').click();
            });
        });
    });

    describe('#hint', function () {
        it('set string', function () {
            var app = laydate.render({
                elem: '#test-div',
                show: true
            });

            expect(app.hint).to.be.a('function', '.hint 必须是方法');
            app.hint('layui');
            expect($('.layui-laydate-hint').text()).to.equal('layui');
        });

        it('timeout 3000', function (done) {
            var app = laydate.render({
                elem: '#test-div',
                show: true
            });

            app.hint('layui');
            expect($('.layui-laydate-hint').length).to.equal(1);
            setTimeout(function () {
                expect($('.layui-laydate-hint').length).to.equal(0);
                done();
            }, 3500);
        });
    });
    describe('.getEndDate', function () {
        it('default params and return value', function () {
            expect(laydate.getEndDate).to.be.a('function', 'laydate.getEndDate 必须是方法');
            expect(laydate.getEndDate()).to.be.a('number', 'laydate.getEndDate 返回值必须是数字');
            expect(laydate.getEndDate(10, 2017)).to.be.a('number', 'laydate.getEndDate 返回值必须是数字');
            expect(laydate.getEndDate(10)).to.be.a('number', 'laydate.getEndDate 返回值必须是数字');
        });

        it('getEndDate(year)', function () {
            expect(laydate.getEndDate(10)).to.equal(31, '10月最后一天为31');
            expect(laydate.getEndDate(11)).to.equal(30, '11月最后一天为30');
            expect(laydate.getEndDate(11, 2017)).to.equal(30, '2017年11月最后一天为30');
            expect(laydate.getEndDate(10, 2017)).to.equal(31, '2017年10月最后一天为31');
            expect(laydate.getEndDate(2, 2017)).to.equal(28, '2017年2月最后一天为28');
            expect(laydate.getEndDate(2, 2016)).to.equal(29, '2016年2月最后一天为29');
        });
    });

    describe('lay', function () {
        describe('lay.stope', function () {
            it('stopPropagation', function (done) {
                lay.stope({
                    stopPropagation: function (e) {
                        expect(e).to.be.undefined;
                        done();
                    }
                });
            });

            it('cancelBubble', function () {
                var event = {};
                lay.stope(event);
                expect(event.cancelBubble).to.be.true;
            });

            // ie中不支持, 只针对phantomjs测试
            if (IS_PHANTOMJS) {
                it('window.event', function () {
                    var old = window.event;
                    var event = window.event = {};
                    lay.stope();
                    expect(event.cancelBubble).to.be.true;
                    window.event = old;
                });
            }
        });

        describe('lay.extend', function () {
            it('default params and return value', function () {
                expect(lay.extend).to.be.a('function', '必须是方法');
                expect(lay.extend()).to.be.a('object', '返回值必须是对象');
                expect(lay.extend({})).to.be.a('object', '返回值必须是对象');
                expect(lay.extend({}, {})).to.be.a('object', '返回值必须是对象');
            });

            it('multiple object', function () {
                expect(lay.extend({}, {})).to.deep.equal({});
                expect(lay.extend(true, {})).to.deep.equal({});
                expect(lay.extend(true, {a: 1}, {b: 2})).to.deep.equal({
                    a: 1,
                    b: 2
                }, '合并多个对象');
                expect(lay.extend({a: 1}, {b: 2})).to.deep.equal({
                    a: 1,
                    b: 2
                }, '合并多个对象');
            });

            it('recursion merge', function () {
                expect(lay.extend({
                    a: 1,
                    b: {
                        b1: 1
                    }
                }, {
                    b: {
                        b2: 1,
                        b3: [1]
                    }
                }, {
                    c: null
                })).to.deep.equal({
                    a: 1,
                    b: {
                        b1: 1,
                        b2: 1,
                        b3: [1]
                    },
                    c: null
                });
            });

            it('clone object', function () {
                var a = {};
                lay.extend(a, {
                    b: 1
                }, {
                    c: []
                });

                expect(a.b).to.equal(1, '污染了原对象');
                expect(a.c).to.deep.equal([], '污染了原对象');
            });
        });

        describe('lay.each', function () {
            it('check params', function () {
                expect(lay.each).to.be.a('function', '必须是方法');
                expect(lay.each()).to.deep.equal(lay, '返回值判断');
                expect(lay.each({})).to.deep.equal(lay);
                expect(lay.each([])).to.deep.equal(lay);
                expect(lay.each({}, function () {
                })).to.deep.equal(lay);
            });

            it('null params', function (done) {
                var index = 0;
                lay.each(null, function (index) {
                    index += 1;
                });
                setTimeout(function () {
                    expect(index).to.equal(0);
                    done();
                });
            });

            it('object each', function (done) {
                lay.each({
                    name: 'layui'
                }, function (key, value) {
                    expect(this + '').to.deep.equal(value).and.equal('layui');
                    expect(key).to.equal('name');
                    done();
                });
            });

            it('array each', function (done) {
                lay.each([
                    'layui'
                ], function (index, value) {
                    expect(this + '').to.deep.equal(value).and.equal('layui');
                    expect(index).to.equal(0);
                    done();
                });
            });

            it('break array each', function () {
                var arr = new Array(100).join(',').split(',');
                var flag = -1;
                lay.each(arr, function (index) {
                    flag = index;
                    if (index > 5) {
                        return true;
                    }
                });
                expect(flag).to.equal(6);

                flag = -1;
                lay.each(arr, function (index) {
                    flag = index;
                    if (index > 5) {
                        return false;
                    }
                });
                expect(flag).to.equal(99);
            });

            it('break object each', function () {
                var obj = {
                    name: 'layui',
                    version: '2.x'
                };
                var flag = null;
                lay.each(obj, function (key) {
                    flag = key;
                    return true;
                });
                expect(flag).to.equal('name');

                flag = null;
                lay.each(obj, function (key) {
                    flag = key;
                    return false;
                });
                expect(flag).to.equal('version');
            });
        });

        describe('lay.elem', function () {
            it('create div', function () {
                expect(lay.elem('div')).to.be.an.instanceof(HTMLElement, '必须是 html 节点');
            });

            it('has error', function () {
                expect(function () {
                    lay.elem([]);
                }).to.throw;

                expect(function () {
                    lay.elem();
                }).to.throw;
            });

            it('set attrs', function () {
                var node = lay.elem('div', {
                    'data-name': 'layui'
                });

                expect($(node).attr('data-name')).to.equal('layui');
            });
        });

        describe('lay.digit', function () {
            it('default params and return value', function () {
                expect(lay.digit).to.be.a('function', '必须是方法');
                expect(lay.digit()).to.equal('undefined', '无参数时返回 undefined');
            });

            it('default length', function () {
                expect(lay.digit(1)).to.equal('01');
                expect(lay.digit(1)).to.equal(lay.digit(1, 2));
                expect(lay.digit(11)).to.equal('11');
                expect(lay.digit('111')).to.equal('111');
            });

            it('set length', function () {
                expect(lay.digit(1, 1)).to.equal('1');
                expect(lay.digit(1, 2)).to.equal('01');
                expect(lay.digit(11, 1)).to.equal('11');
                expect(lay.digit('11', 10)).to.equal('0000000011', '补10位');
                expect(lay.digit(1, 5)).to.equal('00001');
                expect(lay.digit(1, 100).length).to.equal(100, '补100位');
            });
        });

        if (IS_PHANTOMJS) {
            it('lay.ie', function () {
                expect(lay.ie).to.be.a('boolean');
            });
        }
    });

    describe('lay()', function () {
        it('return value', function () {
            expect(lay).to.be.a('function', '必须是方法');
            expect(lay()).to.be.a('object');
        });

        it('#find', function () {
            expect(lay('body').find()[0]).to.be.undefined;
            expect(lay('body').find('.test-test-empty')[0]).to.be.undefined;
            expect(lay('body').find('div')[0]).to.not.be.undefined;
        });

        it('#addClass', function () {
            var $node = lay('#test-div');

            expect($('#test-div').hasClass('layui')).to.be.false;
            expect($node.addClass('layui')).to.deep.equal($node);
            expect($('#test-div').hasClass('layui')).to.be.true;
        });

        it('#removeClass', function () {
            var $node = lay('#test-div');

            lay('#test-div').addClass('layui');
            expect($('#test-div').hasClass('layui')).to.be.true;
            expect($node.removeClass('layui')).to.deep.equal($node);
            expect($('#test-div').hasClass('layui')).to.be.false;
        });

        it('#hasClass', function () {
            expect(lay('#test-div').hasClass('layui')).to.be.false;
            lay('#test-div').addClass('layui');
            expect(lay('#test-div').hasClass('layui')).to.be.true;
            lay('#test-div').removeClass('layui');
            expect(lay('#test-div').hasClass('layui')).to.be.false;
        });

        it('#attr', function () {
            $('#test-div').attr('data-name', 'layui');
            expect(lay('#test-div').attr('data-name')).to.equal('layui');

            var $node = lay('#test-div');
            expect($node.attr('data-name', 'layui-2')).to.deep.equal($node);
            expect(lay('#test-div').attr('data-name')).to.equal('layui-2');

            expect(lay('#test-test-empty').attr('data-name')).to.be.undefined;
        });

        it('#removeAttr', function () {
            var $node = lay('#test-div');

            lay('#test-div').attr('data-name', 'layui');
            expect(lay('#test-div').attr('data-name')).to.equal('layui');

            expect(lay('#test-div').removeAttr('data-name')).to.deep.equal($node);
            expect(lay('#test-div').attr('data-name')).to.not.equal('layui');
        });

        it('#html', function () {
            var str = '<b>layui</b>';
            var $node = lay('#test-div');
            expect($node.html(str)).to.deep.equal($node);

            expect($('#test-div').html()).to.equal(str);
        });

        it('#val', function () {
            var $node = lay('#test-input');
            expect($node.val('layui')).to.deep.equal($node);
            expect($('#test-input').val()).to.equal('layui');
        });

        it('#append', function () {
            var $node = lay('#test-div');

            expect($node.append('<b>1</b>')).to.deep.equal($node);
            lay('#test-div').append('<b>2</b>');
            expect($('#test-div').html()).to.equal('<b>1</b><b>2</b>');
            $('#test-div').empty();

            var node = $('<b />').html('layui').get(0);
            lay('#test-div').append(node);
            expect($('#test-div').html()).to.equal('<b>layui</b>');
        });

        it('#remove', function () {
            lay('#test-div').append('<div>1</div>');
            expect($('#test-div').children().length).to.equal(1);
            lay('#test-div').remove($('#test-div').children().get(0));
            expect($('#test-div').children().length).to.equal(0);

            lay('#test-div').append('<div>1</div>');
            expect($('#test-div').children().length).to.equal(1);
            lay('#test-div div').remove();
            expect($('#test-div').children().length).to.equal(0);
        });

        it('#on', function (done) {
            lay('#test-div').on('click', function (event) {
                expect(event).to.be.not.undefined;
                done();
            });
            $('#test-div').click();
        });

        // it('#off', function (done) {
        //   var fn = function () {
        //     done('off error');
        //   };
        //   lay('#test-div').on('click', fn).off('click', fn);
        //   $('#test-div').click();
        //   setTimeout(function () {
        //     done();
        //   });
        // });
    });
});

/* eslint-enable max-nested-callbacks, fecs-indent */
